package org.bizbundles.translate;

import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import java.net.URLEncoder;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;


/**
 * Copyright 2007 BizBundle.org
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * <p/>
 * <p><b>This is very EXPERIMENTAL ues with CAUTION</b></p>
 *
 * @author Steve Roach
 * @since: Nov 12, 2007
 * 5:30:38 PM
 */
public class GoogleTranslateApiHelper
{

    private String languagePair;
    private static final String GOOGLE_TRANSLATE_URL = "http://translate.google.com/translate_t?";

    public GoogleTranslateApiHelper(String languagePair)
    {
        this.languagePair = languagePair;
    }

    public String translate(String textToTranslate)
    {
        return translate(textToTranslate, false);
    }
    private String translate(String textToTranslate, boolean encodeUtf8)
    {
        try
        {
            String url = GOOGLE_TRANSLATE_URL + "langpair=" + languagePair + "&text=" + textToTranslate;
            Parser parser = new Parser();
            parser.setURL(url);
            if(encodeUtf8)
            {
                parser.setEncoding("utf-8");
            }
            NodeList nl = parser.parse(null);
            Node[] nodes = nl.toNodeArray();
            for (Node node : nodes)
            {
                Node body = node.getLastChild();
                NodeList divs = body.getChildren().extractAllNodesThatMatch(new TagNameFilter("div"), true);
                for (int j = 0; j < divs.size(); j++)
                {
                    Node divNodes = divs.elementAt(j);
                    if (divNodes.getText().contains(new StringBuffer("result_box")))
                    {
                        //System.out.print(textToTranslate + " `converted to` " + divNodes.toPlainTextString() + " `unicode values are'");
                        return divNodes.toPlainTextString();
                        //return convertToHex(divNodes.toPlainTextString());
                    }
                }
            }
        }
        catch (ParserException e)
        {
            throw new RuntimeException(e);
        }
        return "";
    }





    /**
     * encodes a string of 4-digit hex numbers to unicode
     * <br />
     * Note: this method is slower than hexToString(String,StringBuffer)
     *
     * @param hex string of 4-digit hex numbers
     * @return normal java string
     */
    protected String hexToString(String hex)
    {
        if (hex == null)
        {
            return "";
        }
        int length = hex.length() & -4;
        StringBuffer result = new StringBuffer(length / 4);
        hexToString(hex, result);
        return result.toString();
    }

    /**
     * encodes a string of 4-digit hex numbers to unicode
     *
     * @param hex string of 4-digit hex numbers
     * @param out normal java string
     * todo to improve performance, implement a table-lookup instead of parseInt(substring())
     */
    private void hexToString(String hex, StringBuffer out)
    {
        if (hex == null)
        {
            return;
        }
        int length = hex.length() & -4;
        for (int pos = 0; pos < length; pos += 4)
        {
            int this_char = 0;
            try
            {
                this_char = Integer.parseInt(hex.substring(pos, pos + 4), 16);
            }
            catch (NumberFormatException NF_Ex)
            { /* dont care*/ }
            out.append((char) this_char);
        }
    }


    

    protected String escapeUnicodeString(String str, boolean escapeAscii)
    {
        StringBuffer ostr = new StringBuffer();

        for (int i = 0; i < str.length(); i++)
        {

            char ch = str.charAt(i);

            if (!escapeAscii && ((ch >= 0x0020) && (ch <= 0x007e)))
            {
                ostr.append(ch);
            }
            else
            {

                ostr.append("\\u");

                String hex = Integer.toHexString(str.charAt(i) & 0xFFFF);
                for (int j = 0; j < 4 - hex.length(); j++)
                {
                    ostr.append("0");
                }

                ostr.append(hex.toUpperCase(Locale.ENGLISH));

            }

        }

        return (new String(ostr));

    }

    public static void main(String[] args) throws Exception
    {
        final List<TableData> list = new LinkedList<TableData>();

        GoogleTranslateApiHelper apiHelper = new GoogleTranslateApiHelper("en|es");
        addDisplayTableElement(apiHelper, list, "Welcome");
        addDisplayTableElement(apiHelper, list, "Thank You");
        addDisplayTableElement(apiHelper, list, "My Compliments To The Chef");

        apiHelper = new GoogleTranslateApiHelper("en|ja");

        addDisplayTableElement(apiHelper, list, "Welcome");
        addDisplayTableElement(apiHelper, list, "Thank You");
        addDisplayTableElement(apiHelper, list, "My Compliments To The Chef");

        apiHelper = new GoogleTranslateApiHelper("en|fr");

        addDisplayTableElement(apiHelper, list, "Welcome");
        addDisplayTableElement(apiHelper, list, "Thank You");
        addDisplayTableElement(apiHelper, list, "My Compliments To The Chef");


        apiHelper = new GoogleTranslateApiHelper("fr|en");

        addDisplayTableElement(apiHelper, list, "Bienvenue");
        addDisplayTableElement(apiHelper, list, "Merci");
        addDisplayTableElement(apiHelper, list, "Mes compliments au Chef");


        apiHelper = new GoogleTranslateApiHelper("es|en");

        addDisplayTableElement(apiHelper, list, "Bienvenido");
        addDisplayTableElement(apiHelper, list, "Gracias");
        addDisplayTableElement(apiHelper, list, "Mi atentamente al Chef");

        apiHelper = new GoogleTranslateApiHelper("ja|en");

        addDisplayTableElement(apiHelper, list, URLEncoder.encode("\u30AF\u30A4\u30C3\u30AF\u30D6\u30E9\u30A6\u30F3\u30D5\u30A9\u30C3\u30AF\u30B9\u6025\u5897\u3059\u308B\u6020\u60F0\u306A\u72AC\u304C\u3044\u307E\u3059\u3002", "UTF-8"),true);

        addDisplayTableElement(apiHelper, list, URLEncoder.encode(apiHelper.hexToString("308830463053305D"),"UTF-8"),true);
        //addDisplayTableElement(apiHelper, list, URLEncoder.encode(apiHelper.hexToString("3042308a304c30683046"), "UTF-8"),true);
        //addDisplayTableElement(apiHelper, list, URLEncoder.encode(apiHelper.hexToString("79c130928912308130b730a730d5"), "UTF-8"),true);

        final String[] columns = {"Source Text", "Translated text", "Hex Value"};
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                TableOutput output = new TableOutput(columns, list);
                output.createAndShowGUI(columns, list);
            }
        });
        //StringTokenizer tokenizer = new StringTokenizer(apiHelper.translate("Welcome"),"\\u");
        //System.out.println(tokenizer.countTokens());
    }

    private static void addDisplayTableElement(GoogleTranslateApiHelper apiHelper, List<TableData> list, String source)
    {
        addDisplayTableElement(apiHelper, list, source, false);
    }

    private static void addDisplayTableElement(GoogleTranslateApiHelper apiHelper, List<TableData> list, String source, boolean encode)
    {

        String result;
        if (encode)
        {
            result = apiHelper.translate(source, true);
        }
        else
        {
            result = apiHelper.translate(source);
        }

        TableData data = new TableData(source, result, apiHelper.escapeUnicodeString(result, false));
        list.add(data);
        try
        {
            Thread.sleep(1000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

}


